<script setup lang="ts">
import { ref, computed, onUpdated } from 'vue'
import type { ComPaginationTableHeader } from '@/interface/index'
import { formatInvalidValue } from '@/utils'
import NoData from '@/components/NoData.vue'
// 控制checkbox状态
const selections = ref<boolean[]>([])
const props = defineProps({
  data: {
    type: Array,
    default: () => [],
  },
  height: {
    type: [String, Number],
    default: '100%',
  },
  width: {
    type: [String, Number],
    default: '100%',
  },
  showPage: {
    type: Boolean,
    default: false,
  },
  headers: {
    type: Array<ComPaginationTableHeader>,
    default: () => [],
  },
  currentPage: {
    type: Number,
  },
  total: {
    type: Number,
    default: 0,
  },
  loading: {
    type: Boolean,
    default: false,
  },
  pageSize: {
    type: Number,
  },
  pageSizes: {
    type: Array<number>,
    default: [10, 20, 30, 40, 50, 100, 200],
  },
  tableOptions: {
    type: Object,
  },
  tableEvents: {
    type: Object,
  },
  pageOptions: {
    type: Object,
    default: () => ({
      layout: 'total, sizes, prev, pager, next, jumper',
    }),
  },
})
const tableRef = ref<any>(null)
const emit = defineEmits([
  'currentChange',
  'sizeChange',
  'sizeOrCurrentChange',
  'select',
  'selectAll',
  'sortChange',
  'update:currentPage',
  'update:pageSize',
  'refresh',
  'sortColumn',
])
onUpdated(() => {
  emit('refresh')
})

const currentChange = (curr: number) => {
  emit('update:currentPage', curr)
  emit('currentChange', curr)
  emit('sizeOrCurrentChange')
}
const sizeChange = (size: number) => {
  //切换需要重置
  emit('update:currentPage', 1)
  emit('currentChange', 1)

  emit('update:pageSize', size)
  emit('sizeChange', size)
  emit('sizeOrCurrentChange')
}
// 单选
const selectRow = (row: number, selected: []) => {
  tableRef.value.toggleRowSelection(row, selected)
  const selection = tableRef.value.getSelectionRows()
  emit('select', selection, row)
}
// 选择所有
const selectAll = (selection: []) => {
  if (selection.length > 0) {
    selections.value = selection.map(() => true)
  } else {
    selections.value = selections.value.map(() => false)
  }
  emit('selectAll', selection)
}
// 切换排序
const sortChange = (column: string, prop: object, order: string) => {
  emit('sortColumn', column, prop, order)
}
const showHeaders = computed(() =>
  props.headers.filter(header => header.isVisible && !header.isExpand),
)
// 清空table的选择状态
const clearSelection = () => {
  selections.value = selections.value.map(() => false)
  tableRef.value.clearSelection()
}
// 选择table的选择状态
const toggleRowSelection = (row: any, flag: boolean) => {
  props.data.forEach((item, index) => {
    if (row === item) {
      selections.value[index] = flag
    }
  })
  tableRef.value.toggleRowSelection(row, flag)
}
defineExpose({ clearSelection, table: tableRef, toggleRowSelection })
</script>

<template>
  <div class="table-container">
    <el-table
      @sort-change="sortChange"
      :class="data.length || 'no-data'"
      v-loading="loading"
      ref="tableRef"
      border
      highlight-current-row
      show-overflow-tooltip
      style="overflow: auto; height: 100%"
      :style="{ width: width }"
      :height="height"
      v-bind="$attrs"
      :data="data"
      @select-all="selectAll"
    >
      <template #empty>
        <slot name="empty">
          <no-data :icon-width="80"></no-data>
        </slot>
      </template>
      <el-table-column
        v-for="header of showHeaders"
        v-bind="header"
        :key="header.type || header.prop"
      >
        <template #header>
          <slot :name="'header.' + header.prop" :header="header">{{
            header.label
          }}</slot>
        </template>
        <template #default="scoped">
          <template v-if="header.children!?.length > 0">
            <el-table-column
              v-for="(subHeader, index) of header.children"
              v-bind="subHeader"
              :key="(subHeader.prop! || '') + index"
            >
              <template #header>
                <slot :name="'header.' + subHeader.prop" :header="subHeader"
                  >{{ subHeader.label }}
                </slot>
              </template>
              <template v-if="!subHeader.type" #default="scoped">
                <slot :name="'row.' + subHeader.prop" v-bind="scoped">
                  {{ formatInvalidValue(scoped.row[subHeader.prop!]) }}
                </slot>
              </template>
            </el-table-column>
          </template>
          <template v-else>
            <div v-if="header.type === 'expand'">
              <slot name="row:expand" v-bind="scoped"></slot>
            </div>
            <div v-if="header.type === 'selection'">
              <el-checkbox
                v-model="selections[scoped.$index]"
                @change="selectRow(scoped.row, $event)"
              >
              </el-checkbox>
            </div>
            <div v-if="header.type === 'index'">
              <template v-if="showPage">
                {{ (currentPage! - 1) * pageSize! + (scoped.$index + 1) }}
              </template>
              <template v-else>
                {{ scoped.$index + 1 }}
              </template>
            </div>
            <template v-if="!header.type">
              <slot :name="'row.' + header.prop" v-bind="scoped">
                <div
                  :title="formatInvalidValue(scoped.row[header.prop!])"
                  class="ellipsis"
                >
                  {{ formatInvalidValue(scoped.row[header.prop!]) }}
                </div>
              </slot>
            </template>
          </template>
        </template>
      </el-table-column>
    </el-table>
  </div>
  <div class="page-box" v-if="showPage">
    <el-pagination
      popper-class="my-pagination"
      style="margin-top: 12px"
      :current-page="currentPage"
      @current-change="currentChange"
      @size-change="sizeChange"
      :total="total"
      :page-size="pageSize"
      :page-sizes="pageSizes"
      v-bind="pageOptions"
    />
  </div>
</template>
<script lang="ts">
export default {
  //组件名称
  name: 'ComPaginationTable',
}
</script>
<style lang="scss" scoped>
.table-container {
  flex: 1;
  overflow: auto;
}

.page-box {
  flex-shrink: 0;
  display: flex;
  justify-content: right;
}

:deep(.el-table.no-data) {
  .el-table__empty-block {
    position: static;
  }
}

.ellipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
</style>
